home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBASE102.ARJ / BTDEMO.C < prev    next >
Text File  |  1991-09-23  |  16KB  |  589 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)btdemo.c    1.5 - 91/09/23" */
  5.  
  6. #include <ansi.h>
  7.  
  8. /* ansi headers */
  9. #include <errno.h>
  10. #include <ctype.h>
  11. #include <stdio.h>
  12. #ifdef AC_STDLIB
  13. #include <stdlib.h>
  14. #endif
  15. #ifdef AC_STRING
  16. #include <string.h>
  17. #endif
  18.  
  19. /* library headers */
  20. #include <blkio.h>
  21. #include <btree.h>
  22.  
  23. #ifndef AC_STRING
  24. /* memmove:  memory move */
  25. #ifdef AC_PROTO
  26. void *memmove(void *t, const void *s, size_t n)
  27. #else
  28. void *memmove(t, s, n)
  29. void *t;
  30. const void *s;
  31. size_t n;
  32. #endif
  33. {
  34.     int i = 0;
  35.  
  36.     if (t < s) {
  37.         for (i = 0; i < n; ++i) {
  38.             *((char *)t + i) = *((char *)s + i);
  39.         }
  40.     } else {
  41.         for (i = n - 1; i >= 0; --i) {
  42.             *((char *)t + i) = *((char *)s + i);
  43.         }
  44.     }
  45.  
  46.     return t;
  47. }
  48. #endif
  49.  
  50. /* function declarations */
  51. #ifdef AC_PROTO
  52. int bdlock(btree_t *btp, int ltype);
  53. int putmenu(void);
  54. #else
  55. int bdlock();
  56. int putmenu();
  57. #endif
  58.  
  59. /* comparison function */
  60. #ifdef AC_PROTO
  61. int cmp(const void *p1, const void *p2, size_t n)
  62. #else
  63. int cmp(p1, p2, n)
  64. const void *p1;
  65. const void *p2;
  66. size_t n;
  67. #endif
  68. {
  69.     return strncmp((char *)p1, (char *)p2, n);
  70. }
  71.  
  72. /* constants */
  73. #define LCKTRIES_MAX    (100)        /* maximum lock tries */
  74. #define PROGNAME    "btdemo"    /* default program name */
  75. #define USAGE        "usage: %s filename keysize\n"
  76.                     /* usage message */
  77.  
  78. /* btdemo user requests */
  79. #define REQ_NEXT    ('N')    /* next */
  80. #define REQ_PREV    ('P')    /* previous */
  81. #define REQ_FIRST    ('F')    /* first */
  82. #define REQ_LAST    ('L')    /* last */
  83. #define REQ_INS        ('I')    /* insert */
  84. #define REQ_DEL        ('D')    /* delete */
  85. #define REQ_SRCH    ('S')    /* search */
  86. #define REQ_CUR        ('C')    /* current */
  87. #define REQ_ALL        ('A')    /* all */
  88. #define REQ_MENU    ('M')    /* help */
  89. #define REQ_QUIT    ('Q')    /* quit */
  90.  
  91. /*man---------------------------------------------------------------------------
  92. NAME
  93.      btdemo - btree demonstration program
  94.  
  95. SYNOPSIS
  96.      btdemo filename keysize
  97.  
  98. DESCRIPTION
  99.      btdemo is a demonstration program for the btree library.  It
  100.      allows interactive direct access to a btree with keys having a
  101.      single field of string data sorted by strncmp in ascending order.
  102.  
  103. SEE ALSO
  104.      btree.
  105.  
  106. WARNING
  107.      btdemo should be used only on btrees with keys having a single
  108.      field of string data sorted by strncmp in ascending order.  Use
  109.      on other btrees will produce unpredictable results and corrupt
  110.      the file if modifications are attempted.
  111.  
  112. ------------------------------------------------------------------------------*/
  113. #ifdef AC_PROTO
  114. int main(int argc, char *argv[])
  115. #else
  116. int main(argc, argv)
  117. int argc;
  118. char *argv[];
  119. #endif
  120. {
  121.     char *        progname= PROGNAME;    /* program name */
  122.     btree_t *    btp    = NULL;        /* btree pointer */
  123.     char        buf[256];        /* input buffer */
  124.     char *        endp    = NULL;        /* pointer for strtol fct */
  125.     char filename[FILENAME_MAX + 1];    /* btree file name */
  126.     int        fldc    = 1;        /* field count */
  127.     btfield_t    fldv[1];        /* field definition list */
  128.     int        found    = 0;        /* key found flag */
  129.     void *        key    = NULL;    
  130.     long        keylen    = 0;        /* strtol return */
  131.     size_t        keysize    = 0;        /* key size */
  132.     const int    m    = 4;        /* btree order */
  133.     int        rq    = 0;        /* user request */
  134.  
  135.     /* register termination function to flush blkio buffers */
  136. #ifdef AC_STDLIB
  137.     if (atexit(bcloseall)) {
  138.         fputs("Unable to register termination function to flush database buffers.\n", stderr);
  139.         exit(EXIT_FAILURE);
  140.     }
  141. #else
  142. #define exit(status)    bexit(status)
  143. #endif
  144.  
  145.     /* process command line */
  146.     if (argc > 0) {        /* program name */
  147.         progname = *argv;
  148.         --argc;
  149.         ++argv;
  150.     }
  151.     if (argc < 1) {        /* filename */
  152.         fprintf(stderr, USAGE, progname);
  153.         exit(EXIT_FAILURE);
  154.     }
  155.     strncpy(filename, *argv, sizeof(filename));
  156.     filename[sizeof(filename) - 1] = NUL;
  157.     --argc;
  158.     ++argv;
  159.     if (argc < 1) {        /* keysize */
  160.         fprintf(stderr, USAGE, progname);
  161.         exit(EXIT_FAILURE);
  162.     }
  163.     errno = 0;
  164.     keylen = strtol(*argv, &endp, 10);
  165.     if (errno == ERANGE) {
  166.         fprintf(stderr, "%s: keysize argument out of range.\n", progname);
  167.         fprintf(stderr, USAGE, progname);
  168.         exit(EXIT_FAILURE);
  169.     }
  170.     if (endp != NULL) {
  171.         if (endp[0] != NUL) {
  172.             fprintf(stderr, USAGE, progname);
  173.             exit(EXIT_FAILURE);
  174.         }
  175.     }
  176.     if (keylen < 1) {
  177.         fprintf(stderr, USAGE, progname);
  178.         exit(EXIT_FAILURE);
  179.     }
  180.     keysize = (size_t)keylen;
  181.     --argc;
  182.     ++argv;
  183.     if (argc != 0) {
  184.         fprintf(stderr, USAGE, progname);
  185.         exit(EXIT_FAILURE);
  186.     }
  187.  
  188.     /* open btree */
  189.     fldc = 1;
  190.     fldv[0].offset = 0;
  191.     fldv[0].len = keysize;
  192.     fldv[0].cmp = cmp;
  193.     fldv[0].flags = BT_FASC;
  194.     btp = btopen(filename, "r+", fldc, fldv);
  195.     if (btp == NULL) {
  196.         if (errno != ENOENT) {
  197.             fprintf(stderr, "*** Error %d opening btree.\n", errno);
  198.             exit(EXIT_FAILURE);
  199.         }
  200.         printf("btree %s does not exist.  Creating.\n\n", filename);
  201.         if (btcreate(filename, m, keysize, fldc, fldv) == -1) {
  202.             fprintf(stderr, "*** Error %d creating btree.\n", errno);
  203.             exit(EXIT_FAILURE);
  204.         }
  205.         btp = btopen(filename, "r+", fldc, fldv);
  206.         if (btp == NULL) {
  207.             fprintf(stderr, "*** Error %d opening btree.\n", errno);
  208.             exit(EXIT_FAILURE);
  209.         }
  210.     }
  211.     /* check key size */
  212.     if (bdlock(btp, BT_RDLCK) == -1) {    /* must lock once to read key size from file */
  213.         fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  214.         exit(EXIT_FAILURE);
  215.     }
  216.     if (bdlock(btp, BT_UNLCK) == -1) {
  217.         fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  218.         exit(EXIT_FAILURE);
  219.     }
  220.     if (keysize != btkeysize(btp)) {
  221.         printf("Incorrect keysize.  Keysize for this btree is %lu.\n", (unsigned long)btkeysize(btp));
  222.         exit(EXIT_FAILURE);
  223.     }
  224.  
  225.     /* allocate key storage */
  226.     key = calloc(btkeysize(btp), (size_t)1);
  227.     if (key == NULL) {
  228.         fprintf(stderr, "Insufficient memory for key.\n");
  229.         exit(EXIT_FAILURE);
  230.     }
  231.  
  232.     puts("\n--------------------------------------------------");
  233.     puts("|           btree Library Demo Program           |");
  234.     puts("--------------------------------------------------\n");
  235.     putmenu();
  236.  
  237.     /* main loop */
  238.     for (;;) {
  239.         fputs("Enter selection:  ", stdout);
  240.         fgets(buf, (int)sizeof(buf), stdin);
  241.         if (buf[strlen(buf) - 1] == '\n') {
  242.             buf[strlen(buf) - 1] = NUL;
  243.         }
  244.         /* add string library function to extract leading spaces */
  245.         rq = toupper(*buf);
  246.         if (rq == REQ_QUIT) {    /* quit btdemo */
  247.             break;
  248.         }
  249.         if (rq == NUL) {    /* default to next key */
  250.             rq = REQ_NEXT;
  251.         }
  252. #if 0
  253.         if (rq == 'X') {
  254.             if (bt_dgbtree(btp, btp->bthdr.root, stdout) == -1) {
  255.                 perror("bt_dgbtree");
  256.                 exit(EXIT_FAILURE);
  257.             }
  258.             continue;
  259.         }
  260. #endif
  261.         switch (rq) {
  262.         case REQ_NEXT:    /* next key */
  263.             if (bdlock(btp, BT_RDLCK) == -1) {
  264.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  265.                 exit(EXIT_FAILURE);
  266.             }
  267.             if (btkeycnt(btp) == 0) {
  268.                 printf("The btree is empty.\n\n");
  269.                 if (bdlock(btp, BT_UNLCK) == -1) {
  270.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  271.                     exit(EXIT_FAILURE);
  272.                 }
  273.                 break;
  274.             }
  275.             found = btsearch(btp, key);
  276.             if (found == -1) {
  277.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  278.                 exit(EXIT_FAILURE);
  279.             }
  280.             if (found == 1) {
  281.                 if (btnext(btp) == -1) {
  282.                     fprintf(stderr, "*** Error %d finding next key.\n", errno);
  283.                     exit(EXIT_FAILURE);
  284.                 }
  285.             }
  286.             if (btcursor(btp) == NULL) {
  287.                 puts("On last key.\n");
  288.             } else {
  289.                 if (btgetk(btp, key) == -1) {
  290.                     fprintf(stderr, "*** Error %d reading key.\n", errno);
  291.                     exit(EXIT_FAILURE);
  292.                 }
  293.                 printf("The next key is %s.\n\n", (char *)key);
  294.             }
  295.             if (bdlock(btp, BT_UNLCK) == -1) {
  296.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  297.                 exit(EXIT_FAILURE);
  298.             }
  299.             break;    /* case REQ_NEXT: */
  300.         case REQ_PREV:    /* previous key */
  301.             if (bdlock(btp, BT_RDLCK) == -1) {
  302.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  303.                 exit(EXIT_FAILURE);
  304.             }
  305.             if (btkeycnt(btp) == 0) {
  306.                 puts("The btree is empty.\n");
  307.                 if (bdlock(btp, BT_UNLCK) == -1) {
  308.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  309.                     exit(EXIT_FAILURE);
  310.                 }
  311.                 break;
  312.             }
  313.             found = btsearch(btp, key);
  314.             if (found == -1) {
  315.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  316.                 exit(EXIT_FAILURE);
  317.             }
  318.             if (found == 1) {
  319.                 if (btprev(btp) == -1) {
  320.                     fprintf(stderr, "*** Error %d finding previous key.\n", errno);
  321.                     exit(EXIT_FAILURE);
  322.                 }
  323.             }
  324.             if (btcursor(btp) == NULL) {
  325.                 puts("On first key.\n");
  326.             } else {
  327.                 if (btgetk(btp, key) == -1) {
  328.                     fprintf(stderr, "*** Error %d reading key.\n", errno);
  329.                     exit(EXIT_FAILURE);
  330.                 }
  331.                 printf("The previous key is %s.\n\n", (char *)key);
  332.             }
  333.             if (bdlock(btp, BT_UNLCK) == -1) {
  334.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  335.                 exit(EXIT_FAILURE);
  336.             }
  337.             break;    /* case REQ_PREV: */
  338.         case REQ_FIRST:    /* first key */
  339.             if (bdlock(btp, BT_RDLCK) == -1) {
  340.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  341.                 exit(EXIT_FAILURE);
  342.             }
  343.             if (btkeycnt(btp) == 0) {
  344.                 puts("The btree is empty.\n");
  345.                 if (bdlock(btp, BT_UNLCK) == -1) {
  346.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  347.                     exit(EXIT_FAILURE);
  348.                 }
  349.                 break;
  350.             }
  351.             if (btfirst(btp) == -1) {
  352.                 fprintf(stderr, "*** Error %d finding first key.\n", errno);
  353.                 exit(EXIT_FAILURE);
  354.             }
  355.             if (btgetk(btp, key) == -1) {
  356.                 fprintf(stderr, "*** Error %d reading key.\n", errno);
  357.                 exit(EXIT_FAILURE);
  358.             }
  359.             if (bdlock(btp, BT_UNLCK) == -1) {
  360.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  361.                 exit(EXIT_FAILURE);
  362.             }
  363.             printf("The first key is %s.\n\n", (char *)key);
  364.             break;    /* case REQ_FIRST: */
  365.         case REQ_LAST:    /* last key */
  366.             if (bdlock(btp, BT_RDLCK) == -1) {
  367.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  368.                 exit(EXIT_FAILURE);
  369.             }
  370.             if (btkeycnt(btp) == 0) {
  371.                 puts("The btree is empty.\n");
  372.                 if (bdlock(btp, BT_UNLCK) == -1) {
  373.                     fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  374.                     exit(EXIT_FAILURE);
  375.                 }
  376.                 break;
  377.             }
  378.             if (btlast(btp) == -1) {
  379.                 fprintf(stderr, "*** Error %d finding last key.\n", errno);
  380.                 exit(EXIT_FAILURE);
  381.             }
  382.             if (btgetk(btp, key) == -1) {
  383.                 fprintf(stderr, "*** Error %d reading key.\n", errno);
  384.                 exit(EXIT_FAILURE);
  385.             }
  386.             if (bdlock(btp, BT_UNLCK) == -1) {
  387.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  388.                 exit(EXIT_FAILURE);
  389.             }
  390.             printf("The last key is %s.\n", (char *)key);
  391.             break;    /* case REQ_LAST: */
  392.         case REQ_INS:    /* insert key */
  393.             printf("Enter key to insert:  ");
  394.             memset(key, 0, btkeysize(btp));
  395.             fgets(buf, (int)sizeof(buf), stdin);
  396.             if (buf[strlen(buf) - 1] == '\n') {
  397.                 buf[strlen(buf) - 1] = NUL;
  398.             }
  399.             strncpy((char *)key, buf, btkeysize(btp));
  400.             ((char *)key)[btkeysize(btp) - 1] = NUL;
  401.             if (bdlock(btp, BT_WRLCK) == -1) {
  402.                 fprintf(stderr, "*** Error %d write locking btree.\n", errno);
  403.                 exit(EXIT_FAILURE);
  404.             }
  405.             if (btinsert(btp, key) == -1) {
  406.                 if (errno == BTEDUP) {
  407.                     printf("%s is already in the btree.\n\n", (char *)key);
  408.                 } else {
  409.                     fprintf(stderr, "*** Error %d inserting key into btree.\n", errno);
  410.                     exit(EXIT_FAILURE);
  411.                 }
  412.             } else {
  413.                 printf("%s inserted in btree.\n\n", (char *)key);
  414.             }
  415.             if (bdlock(btp, BT_UNLCK) == -1) {
  416.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  417.                 exit(EXIT_FAILURE);
  418.             }
  419.             break;    /* case REQ_INS: */
  420.         case REQ_DEL:    /* delete key */
  421.             fputs("Enter key to delete:  ", stdout);
  422.             memset(key, 0, btkeysize(btp));
  423.             fgets(buf, (int)sizeof(buf), stdin);
  424.             if (buf[strlen(buf) - 1] == '\n') {
  425.                 buf[strlen(buf) - 1] = NUL;
  426.             }
  427.             strncpy((char *)key, buf, btkeysize(btp));
  428.             ((char *)key)[btkeysize(btp) - 1] = NUL;
  429.             if (bdlock(btp, BT_WRLCK) == -1) {
  430.                 fprintf(stderr, "*** Error %d write locking btree.\n", errno);
  431.                 exit(EXIT_FAILURE);
  432.             }
  433.             if (btdelete(btp, key) == -1) {
  434.                 if (errno == BTENKEY) {
  435.                     printf("%s not found.\n\n", (char *)key);
  436.                 } else {
  437.                     fprintf(stderr, "*** Error %d deleting key.\n", errno);
  438.                     exit(EXIT_FAILURE);
  439.                 }
  440.             } else {
  441.                 printf("%s deleted from btree.\n\n", (char *)key);
  442.             }
  443.             if (bdlock(btp, BT_UNLCK) == -1) {
  444.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  445.                 exit(EXIT_FAILURE);
  446.             }
  447.             break;    /* case REQ_DEL: */
  448.         case REQ_SRCH:    /* search for key */
  449.             fputs("Enter search key:  ", stdout);
  450.             memset(key, 0, btkeysize(btp));
  451.             fgets(buf, (int)sizeof(buf), stdin);
  452.             if (buf[strlen(buf) - 1] == '\n') {
  453.                 buf[strlen(buf) - 1] = NUL;
  454.             }
  455.             strncpy((char *)key, buf, btkeysize(btp));
  456.             ((char *)key)[btkeysize(btp) - 1] = NUL;
  457.             if (bdlock(btp, BT_RDLCK) == -1) {
  458.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  459.                 exit(EXIT_FAILURE);
  460.             }
  461.             found = btsearch(btp, key);
  462.             if (found == -1) {
  463.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  464.                 exit(EXIT_FAILURE);
  465.             }
  466.             if (found == 1) {
  467.                 printf("%s found.\n", (char *)key);
  468.             } else {
  469.                 printf("%s not found.\n", (char *)key);
  470.             }
  471.             if (bdlock(btp, BT_UNLCK) == -1) {
  472.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  473.                 exit(EXIT_FAILURE);
  474.             }
  475.             break;    /* case REQ_SRCH: */
  476.         case REQ_CUR:    /* current key */
  477.             if (bdlock(btp, BT_RDLCK) == -1) {
  478.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  479.                 exit(EXIT_FAILURE);
  480.             }
  481.             found = btsearch(btp, key);
  482.             if (found == -1) {
  483.                 fprintf(stderr, "*** Error %d searching for key.\n", errno);
  484.                 exit(EXIT_FAILURE);
  485.             }
  486.             if (found == 1) {
  487.                 printf("Current key: %s.\n", (char *)key);
  488.             } else {
  489.                 printf("No current key.\n");
  490.             }
  491.             if (bdlock(btp, BT_UNLCK) == -1) {
  492.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  493.                 exit(EXIT_FAILURE);
  494.             }
  495.             break;    /* case REQ_CUR: */
  496.         case REQ_ALL:    /* list all keys */
  497.             if (bdlock(btp, BT_RDLCK) == -1) {
  498.                 fprintf(stderr, "*** Error %d read locking btree.\n", errno);
  499.                 exit(EXIT_FAILURE);
  500.             }
  501.             printf("There are %lu keys in the btree.\n\n", btkeycnt(btp));
  502.             if (btsetcur(btp, NULL) == -1) {
  503.                 fprintf(stderr, "*** Error %d setting cursor.\n", errno);
  504.                 exit(EXIT_FAILURE);
  505.             }
  506.             for (;;) {
  507.                 if (btnext(btp) == -1) {
  508.                     fprintf(stderr, "*** Error %d finding next key.\n", errno);
  509.                     exit(EXIT_FAILURE);
  510.                 }
  511.                 if (btcursor(btp) == NULL) {
  512.                     break;
  513.                 }
  514.                 if (btgetk(btp, key) == -1) {
  515.                     fprintf(stderr, "*** Error %d reading key.\n", errno);
  516.                     exit(EXIT_FAILURE);
  517.                 }
  518.                 puts((char *)key);
  519.             }
  520.             putchar((int)'\n');
  521.             if (bdlock(btp, BT_UNLCK) == -1) {
  522.                 fprintf(stderr, "*** Error %d unlocking btree.\n", errno);
  523.                 exit(EXIT_FAILURE);
  524.             }
  525.             break;    /* case REQ_ALL: */
  526.         case REQ_MENU:    /* menu */
  527.             putmenu();
  528.             break;    /* case REQ_MENU: */
  529.         default:
  530.             printf("Invalid selection.\a\n");
  531.             break;    /* default: */
  532.         }
  533.     }
  534.  
  535.     /* close btree */
  536.     if (btclose(btp) == -1) {
  537.         fprintf(stderr, "*** Error %d closing btree.\n", errno);
  538.         exit(EXIT_FAILURE);
  539.     }
  540.  
  541.     exit(EXIT_SUCCESS);
  542. }
  543.  
  544. /* bdlock:  btdemo lock */
  545. #ifdef AC_PROTO
  546. int bdlock(btree_t *btp, int ltype)
  547. #else
  548. int bdlock(btp, ltype)
  549. btree_t *btp;
  550. int ltype;
  551. #endif
  552. {
  553.     int i = 0;
  554.  
  555.     for (i = 0; i < LCKTRIES_MAX; ++i) {
  556.         if (btlock(btp, ltype) == -1) {
  557.             if (errno == EAGAIN) {
  558.                 continue;
  559.             }
  560.             return -1;
  561.         } else {
  562.             errno = 0;
  563.             return 0;
  564.         }
  565.     }
  566.  
  567.     errno = EAGAIN;
  568.     return -1;
  569. }
  570.  
  571. /* putmenu:  display menu */
  572. #ifdef AC_PROTO
  573. int putmenu(void)
  574. #else
  575. int putmenu()
  576. #endif
  577. {
  578.     puts("-----------------------MENU-----------------------");
  579.     puts("| N - Next key           P - Previous key        |");
  580.     puts("| F - First key          L - Last key            |");
  581.     puts("| I - Insert key         D - Delete key          |");
  582.     puts("| S - Search for key     C - Current key         |");
  583.     puts("| A - display All keys                           |");
  584.     puts("| M - Menu               Q - Quit                |");
  585.     puts("--------------------------------------------------");
  586.  
  587.     return 0;
  588. }
  589.